package common

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"os"
)

// NewZapLogger 创建并返回一个新的 zap.Logger 实例
// logLevel: 日志级别，如 "DEBUG" 或 "INFO"
// logFilePath: 日志文件路径
func NewZapLogger(logLevel string, logFilePath string) *zap.Logger {
	// 创建一个原子级别变量，用于动态设置日志级别
	atomicLevel := zap.NewAtomicLevel()

	// 根据传入的日志级别设置原子级别
	switch logLevel {
	case "DEBUG":
		atomicLevel.SetLevel(zapcore.DebugLevel)
	case "INFO":
		atomicLevel.SetLevel(zapcore.InfoLevel)
	default:
		atomicLevel.SetLevel(zapcore.InfoLevel)
	}

	// 配置日志的编码格式
	encoderConfig := zapcore.EncoderConfig{
		TimeKey:        "time",                                                 // 时间字段
		LevelKey:       "level",                                                // 日志级别字段
		NameKey:        "name",                                                 // 日志记录器名称字段
		CallerKey:      "line",                                                 // 调用者字段（代码行号）
		MessageKey:     "msg",                                                  // 日志消息字段
		FunctionKey:    "func",                                                 // 函数名字段
		StacktraceKey:  "stacktrace",                                           // 堆栈跟踪字段
		LineEnding:     zapcore.DefaultLineEnding,                              // 行结束符
		EncodeLevel:    zapcore.LowercaseLevelEncoder,                          // 日志级别编码（小写）
		EncodeTime:     zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05.000"), // 时间编码格式
		EncodeDuration: zapcore.SecondsDurationEncoder,                         // 持续时间编码
		EncodeCaller:   zapcore.FullCallerEncoder,                              // 调用者编码（全路径）
		EncodeName:     zapcore.FullNameEncoder,                                // 日志记录器名称编码
	}

	// 配置日志轮转，使用 lumberjack 实现
	writer := &lumberjack.Logger{
		Filename:   logFilePath, // 日志文件路径
		MaxSize:    1,           // 单个日志文件的最大尺寸（单位：MB）
		MaxAge:     30,          // 日志文件的最大保存天数
		MaxBackups: 2,           // 保留的旧日志文件的最大数量
		LocalTime:  true,        // 是否使用本地时间
		Compress:   false,       // 是否压缩旧日志文件
	}

	// 创建用于写入文件的 zapcore.Core
	zapCoreFile := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig), // 使用 JSON 编码器
		zapcore.AddSync(writer),               // 使用日志轮转 writer
		atomicLevel,                           // 日志级别
	)

	// 创建用于输出到控制台的 zapcore.Core
	zapCoreConsole := zapcore.NewCore(
		zapcore.NewJSONEncoder(encoderConfig), // 使用 JSON 编码器
		zapcore.AddSync(os.Stdout),            // 输出到标准输出（控制台）
		atomicLevel,                           // 日志级别
	)

	// 创建一个包含文件和控制台输出的 zapcore.Core
	core := zapcore.NewTee(
		zapCoreFile,    // 文件输出 Core
		zapCoreConsole, // 控制台输出 Core
	)

	// 返回一个新的 zap.Logger 实例，并启用调用者信息（文件名和行号）
	return zap.New(core, zap.AddCaller())
}
